/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

export class MyClass {
  value = 42;

  method(this: MyClass, a: number, b: number): number {
    return this.value + a + b;
  }
}

export type OmittedMethodType = OmitThisParameter<MyClass["method"]>;

export interface User {
  name: string;
  age: number;
}

export class UserService {
  name: string;
  age: number;

  constructor(user: User) {
    this.name = user.name;
    this.age = user.age;
  }

  getUserInfo() {
    return `Name: ${this.name}, Age: ${this.age}`;
  }

  getAge() {
    return this.age;
  }
}

export type UserInfoFunction = UserService['getUserInfo'];
export type ThisTypeOfUserInfoFunction = ThisParameterType<UserInfoFunction>;

export type GetUserAgeFunction = UserService['getAge'];
export type ThisTypeOfGetUserAgeFunction = ThisParameterType<GetUserAgeFunction>;

export function toUppercase<T extends string>(value: T): Uppercase<T> {
  return value.toUpperCase() as Uppercase<T>;
}

export function toLowercase<T extends string>(value: T): Lowercase<T> {
  return value.toLowerCase() as Lowercase<T>;
}

export function capitalize<T extends string>(value: T): Capitalized<T> {
  if (value.length === 0) return value as Capitalized<T>;
  return (value.charAt(0).toUpperCase() + value.slice(1)) as Capitalized<T>;
}

export type Capitalized<StringType extends string> = Capitalize<StringType>;

export function lowercaseFirst<T extends string>(value: T): LowercaseFirst<T> {
  if (value.length === 0) return value as LowercaseFirst<T>;
  return (value.charAt(0).toLowerCase() + value.slice(1)) as LowercaseFirst<T>;
}

export type LowercaseFirst<StringType extends string> = Uncapitalize<StringType>;

type GreetFunction = {
  (this: User): string;
};

function createGreetFunction(fn: GreetFunction): GreetFunction {
  return fn;
}

const greet = createGreetFunction(function () {
  return `Hello, my name is ${this.name} and I am ${this.age} years old.`;
});


const user: User = {
  name: 'John Doe',
  age: 30
};

export const createGreetUser= greet.call(user)

type NoInfer<T> = T extends any ? T : never;

export function identity<T>(value: NoInfer<T>): T {
  return value;
}